package com.ceba.test.modules.storage.job.impl;

import com.ceba.base.enums.FileDefaultStoragePathFlagEnum;
import com.ceba.base.enums.FileStorageFalgeEnum;
import com.ceba.base.exception.CebaException;
import com.ceba.cebautils.DateUtil;
import com.ceba.test.base.config.LogicPathUtil;
import com.ceba.test.base.configs.CebaConfig;
import com.ceba.test.base.configs.CebaPathUtil;
import com.ceba.test.base.enums.CopyFlagEnum;
import com.ceba.test.base.enums.EmailTypeEnum;
import com.ceba.test.base.enums.PeopleTypeEnum;
import com.ceba.test.base.enums.StorageStatusEnum;
import com.ceba.test.base.language.ResourceUtils;
import com.ceba.test.base.language.resources.WebMessages;
import com.ceba.test.modules.email.entity.EmailEntity;
import com.ceba.test.modules.email.entity.EmailRelationPeople;
import com.ceba.test.modules.email.entity.MsgEmailSet;
import com.ceba.test.modules.email.entity.MsgMail;
import com.ceba.test.modules.email.enums.EmailSendTypeEnum;
import com.ceba.test.modules.email.logicService.EmailLogicService;
import com.ceba.test.modules.email.logicService.TemplateContentEmail;
import com.ceba.test.modules.storage.cache.GStorageAddressCache;
import com.ceba.test.modules.storage.entity.GStorageAddress;
import com.ceba.test.modules.storage.job.StorageFileBase;
import com.ceba.test.modules.storage.logicService.GStorageAddressLogicService;
import com.ceba.test.modules.storage.logicService.StorageFileCacheManage;
import com.ceba.test.modules.usermanage.entity.UUser;
import com.ceba.test.modules.usermanage.logicService.UserManageLogicService;
import configs.context.SpringBeans;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class StorageFileJob  implements StorageFileBase {

	private static final long FILE_MIN_SIZE=12288;
	
	private GStorageAddressLogicService gStorageAddressLogicService;
	private static Logger logger = LoggerFactory.getLogger(StorageFileJob.class);

	
	public StorageFileJob(GStorageAddressLogicService gStorageAddressLogicService) {
		this.gStorageAddressLogicService=gStorageAddressLogicService;

	}

	/**
	 * 获取磁盘根目录。（如"d:"、"/data"）
	 * @param path
	 * @return
	 */
	private String getRootPath(String path) {
		if (null == path || path.isEmpty()) {
			throw new CebaException("路径为空，无法计算盘符大小。path=" + path);
		}

		String osName = System.getProperty("os.name").toLowerCase();
		String rootPath = "";
		if (osName.indexOf("linux")>=0) {
			rootPath = path.split("/")[0];
			rootPath = File.separator + rootPath;
		} else if (osName.indexOf("windows")>=0) {
			path.replace("/", "\\");
			rootPath = path.split("\\\\")[0];
		}

		if (rootPath.isEmpty()) {
			throw new CebaException("路径为空，无法计算盘符大小。path=" + path);
		}

		return rootPath;
	}

	@Override
	public void start()throws CebaException {
		if(CebaConfig.FILE_STORAGE_FALG == FileStorageFalgeEnum.NOSTART){return;}
		logger.info("文件管理启动");
		GStorageAddress gStorageAddress=null;
		try{
			//1、更新所有存储地址的存储信息；如果存储地址从“可用”到“已满”，则邮件提醒用户
			updateStorageAddressInfo();
			//2、获取最新可用地址
			gStorageAddress = StorageFileCacheManage.getSystemUseStorageAddress();
		}catch(CebaException idsException){
			logger.error(idsException.toString());
			//提示系统不可用
			warningMsg();
			return;
		}

		//3、无最新可用地址
		if (null == gStorageAddress) {
			//提示系统不可用
			warningMsg();
			return;
		}

		//4、判断是否发送邮件提醒
		if(isHint(gStorageAddress)){
			logger.info("文件管理提醒发送邮件："+gStorageAddress.toString());
			this.hint();
		}
	}

	private void warningMsg() {
		logger.error("***********************严重警告**************************");
		logger.error("无最新可用地址！！！系统无法继续使用！！！");
		logger.error("***********************严重警告**************************");
	}

	/**
	 * 更新所有存储地址的存储信息；
	 * 同时：从“可用”状态变到“已满”状态，会邮件提醒用户
	 */
	private void updateStorageAddressInfo() {
		List<GStorageAddress> addressList=gStorageAddressLogicService.sreachAll();
		for(GStorageAddress address:addressList) {
			logger.info("------------------地址原有信息------------------");
			logger.info("存储地址：" + address.getPath());
			logger.info("总空间：" + address.getCapacity());
			logger.info("可用空间：" + address.getRest());
			logger.info("使用状态：" + address.getStatus());
			logger.info("拷贝状态：" + address.getCopyFlag());

            File file=new File(getRootPath(address.getPath()));
            long totalSpace = file.getTotalSpace() / 1024 / 1024;		//总空间，单位M
            long restSpace = file.getUsableSpace() / 1024 / 1024;		//可用空间，单位M
            long usedSpace = (file.getTotalSpace() - file.getUsableSpace()) / 1024 / 1024;	//已用空间，单位M

            address.setCapacity(totalSpace);
            address.setActualSize(usedSpace);
            address.setRest(restSpace);
            if(restSpace > CebaConfig.FILE_STORAGE_CHANGE_VALUE){
                if (address.getStatus().equalsIgnoreCase(StorageStatusEnum.NOSTART.getCode())) {
                    address.setStatus(StorageStatusEnum.NOSTART.getCode());
                } else if (address.getStatus().equalsIgnoreCase(StorageStatusEnum.FULL.getCode())) {
                    address.setStatus(StorageStatusEnum.NOSTART.getCode());
                } else {
                    address.setStatus(StorageStatusEnum.CAN.getCode());
                }
            } else {
            	//从“可用”状态变到“已满”状态，会邮件提醒用户
            	if (StorageStatusEnum.CAN.getCode().equalsIgnoreCase(address.getStatus())) {
					logger.info("文件管理存储地址块使用完了："+address.getPath());
					this.hint();
				}
                address.setStatus(StorageStatusEnum.FULL.getCode());
            }

			logger.info("------------------地址最新信息------------------");
            logger.info("存储地址：" + address.getPath());
			logger.info("总空间：" + address.getCapacity());
			logger.info("可用空间：" + address.getRest());
			logger.info("使用状态：" + address.getStatus());
			logger.info("拷贝状态：" + address.getCopyFlag());
            updateUseInfo(address);
        }
	}


	/**
	 * 用戶提示
	 * 尊敬的 xxx
	 * 	  在 xxx 系统文件存储管理中，当前名称为“”的存储地址快使用完成，剩余容量（），实际已使用容量（），请及时添加新的存储地址，以免影响你使用。
	 * 个性签名
	 *
	 * 尊敬的 xxx
	 * 	  在 xxx 系统文件存储管理中，文件存储地址已满，系统中没有可用的文件存储地址,请配置文件存储地址，否则会影响正常使用。
	 * 个性签名
	 */
	@Override
	public void hint() throws CebaException {
		EmailLogicService emailLogicService= SpringBeans.getEmailLogicService("emailLogicService");
		MsgMail msgMail=emailLogicService.getMsgEmailByUserId(CebaConfig.ANDMIN_USER_EMAIL_ID);
		MsgEmailSet msgEmailSet=emailLogicService.getMsgEmailSetService().getMsgEmailSetById(EmailSendTypeEnum.STORAGE_CHECK_EMAIL.getDbId());
		if(msgMail == null){
			logger.debug("文件管理存储，用户未配置邮件");
			return;
		}
		Map<String, String> templateMap=new HashMap<String, String>();
		//STORAGE_EMAIL_TITLE=文件存储管理信息
		templateMap.put("#TITLE#", ResourceUtils.getMessage("STORAGE_EMAIL_TITLE"));
		//STORAGE_EMAIL_HONORIFIC=尊敬的
		templateMap.put("#STORAGE_EMAIL_HONORIFIC#", ResourceUtils.getMessage("STORAGE_EMAIL_HONORIFIC"));
		UserManageLogicService userLogicService=SpringBeans.getUserManageLogicService("userManageLogicService");
		String userName=msgMail.getName();
		try {
			UUser user=userLogicService.getUserById(CebaConfig.ANDMIN_USER_ID);
			if(StringUtils.isEmpty(userName)){
				userName=user.getName();
			}
			templateMap.put("#STORAGE_EMAIL_USER#", userName);
		} catch (Exception e) {
			logger.debug("文件管理存储，查询用户报错");
			e.printStackTrace();
		}
		if(StorageFileCacheManage.isSystemUseStorageAddress()){
			/*
			 * TITLE
			 *
			 * 尊敬的 xxx  STORAGE_EMAIL_HONORIFIC STORAGE_EMAIL_USER
			 * 	   在 xxx 系统的文件存储管理中，名称为“”的存储地址，存储空间即将使用完成。剩余容量（6.5）G，实际已使用容量（7.5）G。  STORAGE_EMAIL_CONTENT1
			 *   请及时添加新的存储地址，以免影响您的使用。 STORAGE_EMAIL_CONTENT2
			 * 个性签名 ADMIN_HTML
			 **/
			GStorageAddress gStorageAddress= StorageFileCacheManage.getSystemUseStorageAddress();
			//STORAGE_EMAIL_USE_IN_CONTENT1=在 {0} 系统的文件存储管理中，名称为{1}的存储地址，存储空间即将使用完成。剩余容量（{2}）G，实际已使用容量（{3}）G
			String[] strArrray=new String[4];
			strArrray[0]= WebMessages.getSystemBigVersion();//获取系统全称
			strArrray[1]=gStorageAddress.getName();
			strArrray[2]= ObjectUtils.toString(gStorageAddress.getRest()/1024);
			strArrray[3]=ObjectUtils.toString(gStorageAddress.getActualSize()/1024);
			templateMap.put("#STORAGE_EMAIL_CONTENT1#", ResourceUtils.getMessage("STORAGE_EMAIL_USE_IN_CONTENT1", strArrray));
			//STORAGE_EMAIL_USE_IN_CONTENT2=请及时添加新的存储地址，以免影响您的使用。
			templateMap.put("#STORAGE_EMAIL_CONTENT2#", ResourceUtils.getMessage("STORAGE_EMAIL_USE_IN_CONTENT2"));
		}else{
			/*
			 * 尊敬的 xxx
			 * 	  在 xxx 系统的文件存储管理中，文件存储地址空间已满，系统中没有可用的文件存储空间。
			 *   请配置文件存储地址，否则会影 响正常使用。
			 * 个性签名
			 */
			//STORAGE_EMAIL_USE_FULL_CONTENT1=在 {0} 系统的文件存储管理中，文件存储地址空间已满，系统中没有可用的文件存储空间。
			String[] strArrray=new String[1];
			strArrray[0]=WebMessages.getCompleteProductName();
			templateMap.put("#STORAGE_EMAIL_CONTENT1#", ResourceUtils.getMessage("STORAGE_EMAIL_USE_FULL_CONTENT1", strArrray));
			//STORAGE_EMAIL_USE_FULL_CONTENT2=请配置文件存储地址，否则会影 响正常使用。
			templateMap.put("#STORAGE_EMAIL_CONTENT2#", ResourceUtils.getMessage("STORAGE_EMAIL_USE_FULL_CONTENT2"));
		}
		templateMap.put("#ADMIN_HTML#", msgMail.getContent());
		EmailEntity emailEntity = new EmailEntity();
		emailEntity.setHostName(msgMail.getSmtp());
		emailEntity.setAccount(msgMail.getMail());
		emailEntity.setPassword(msgMail.getPassword());
		emailEntity.setContent(msgEmailSet.getContextTemplate());
		//STORAGE_EMAIL_SEND_SUBJECT=系统的文件存储信息提醒
		emailEntity.setSubject(WebMessages.getSystemBigVersion()+ResourceUtils.getMessage("STORAGE_EMAIL_SEND_SUBJECT"));
		emailEntity.setEmailTypeEnum(EmailTypeEnum.IMAGE_HTML_EMAIL);
		//发件人
		EmailRelationPeople people=new EmailRelationPeople();
		people.setEmail(msgMail.getMail());
		people.setName(userName);
		people.setPeopleTypeEnum(PeopleTypeEnum.RECIPIENTS);
		//收件人
		EmailRelationPeople addPeople=new EmailRelationPeople();
		addPeople.setEmail(msgMail.getMail());
		addPeople.setName(userName);
		addPeople.setPeopleTypeEnum(PeopleTypeEnum.ADDTO);
		List<EmailRelationPeople> peopleList=new ArrayList<>();
		peopleList.add(people);
		peopleList.add(addPeople);
		emailEntity.setPeopleList(peopleList);
		TemplateContentEmail templateContentEmail=new TemplateContentEmail(emailEntity, templateMap);
		templateContentEmail.send();
	}

	@Override
	public boolean copy(GStorageAddress outAddress,GStorageAddress inAddress)throws CebaException{
		if(inAddress == null){
			logger.error("拷贝文件错误:被拷贝对象为空");
			throw new CebaException("拷贝文件错误:被拷贝对象为空");
		}
		if(outAddress == null){
			logger.error("拷贝文件错误:拷贝对象为空");
			throw new CebaException("拷贝文件错误:拷贝对象为空");
		}
		long start=System.currentTimeMillis();
		List<String> virtualList= CebaPathUtil.getNeedCopyDir();
		for(String virtualPath:virtualList){
			String inDir=inAddress.getPath()+virtualPath;
			String outDir=outAddress.getPath()+virtualPath;
			File outDirFile=new File(outDir);
			if(!new File(outDir).exists()){
				outDirFile.mkdirs();
			}
			try {
				FileUtils.copyDirectory(new File(inDir),outDirFile);
			} catch (IOException e) {
				logger.error("拷贝文件错误:拷贝目录是错误:错误目录"+inDir);
				throw new CebaException("拷贝文件错误:拷贝目录是错误:错误目录"+inDir);
			}
		}
		long end=System.currentTimeMillis();
		logger.info("拷贝文件完成：耗时"+(end-start)+"毫秒");
		return true;
	}
	
	/**
	 * 更新使用情况
	 * @param gStorageAddress
	 * @return
	 */
	private boolean updateUseInfo(GStorageAddress gStorageAddress){
		return gStorageAddressLogicService.getgStorageAddressService().edit(gStorageAddress);
	}
	/**
	 * 判断是否提醒
	 * @return
	 */
	private boolean isHint(GStorageAddress gStorageAddress){
		GStorageAddress addresse=StorageFileCacheManage.getNoStart();
		if(addresse != null){
			return false;//不用提醒
		}else{
			return StorageFileCacheManage.isNotUse(CebaConfig.FILE_STORAGE_HINT_VALUE, gStorageAddress);
		}
	}

	public GStorageAddressLogicService getgStorageAddressLogicService() {
		return gStorageAddressLogicService;
	}

	public void setgStorageAddressLogicService(GStorageAddressLogicService gStorageAddressLogicService) {
		this.gStorageAddressLogicService = gStorageAddressLogicService;
	}

	public static void main(String[] args) {
		File in=new File("F:/新建文 (2)/test");
		File out=new File("F:/新建文 (2)/test2");
		try {
			FileUtils.copyDirectory(in, out);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void upgrade() {
		//没启动，没改变 就 改默认路径
		if((CebaConfig.FILE_STORAGE_FALG == null || CebaConfig.FILE_STORAGE_FALG == FileStorageFalgeEnum.NOSTART) && CebaConfig.FILE_DEFAULT_STORAGE_PATH_FLAG == FileDefaultStoragePathFlagEnum.NOCHANGE){
			GStorageAddressLogicService gStorageAddressLogicService=this.getgStorageAddressLogicService();
			gStorageAddressLogicService.updatePath(CebaConfig.FILE_STORAGE_DEFAULT_ID,CebaPathUtil.systemValitPath());
		}
		//启动了，改变
		if(CebaConfig.FILE_STORAGE_FALG == FileStorageFalgeEnum.START &&
				CebaConfig.FILE_DEFAULT_STORAGE_PATH_FLAG == FileDefaultStoragePathFlagEnum.NOCHANGE){
			GStorageAddressLogicService gStorageAddressLogicService=this.getgStorageAddressLogicService();
			GStorageAddress gStorageAddress=gStorageAddressLogicService.getgStorageAddressService().
					sreach(CebaConfig.FILE_STORAGE_DEFAULT_ID);
			boolean boolAdd=false;
			if(gStorageAddress == null){
				gStorageAddress=new GStorageAddress();
				gStorageAddress.setId(CebaConfig.FILE_STORAGE_DEFAULT_ID);
				gStorageAddress.setName("默认地址");
				gStorageAddress.setFilter(gStorageAddress.getFilterStr());
				gStorageAddress.setCopyFlag(CopyFlagEnum.COPY.getCode());
				gStorageAddress.setStatus(StorageStatusEnum.CAN.getCode());
				gStorageAddress.setCreateTime(DateUtil.toDay());
				gStorageAddress.setCreateUser(CebaConfig.ANDMIN_USER_ID);
				gStorageAddress.setUpdateTime(DateUtil.toDay());
				gStorageAddress.setUpdateUser(CebaConfig.ANDMIN_USER_ID);
				boolAdd=true;
			}
			gStorageAddress.setPath(CebaPathUtil.systemValitPath());
			gStorageAddress.setStatus(StorageStatusEnum.CAN.getCode());
			File file=new File(gStorageAddress.getPath());
			//判断磁盘剩余容量  与  总容量一致
			long usable=file.getUsableSpace()/(1024*1024);

			// 最小值 12288
			long minSize=FileUtils.sizeOfDirectory(file)/(1024*1024);
			long _minSize=minSize+FILE_MIN_SIZE;

			if(_minSize > usable){
				gStorageAddress.setCapacity(usable);
			}else{
				gStorageAddress.setCapacity(_minSize);
			}
			gStorageAddress.setRest(gStorageAddress.getCapacity()-minSize);
			gStorageAddress.setActualSize(usable);
			gStorageAddress.setPath(file.getPath());
			//改变默认路径
			boolean bool=false;
			if(boolAdd){
				bool=gStorageAddressLogicService.getgStorageAddressService().add(gStorageAddress);
			}else{
				bool=gStorageAddressLogicService.getgStorageAddressService().
						edit(gStorageAddress);
			}

			//修改个性签名的 图片
			EmailLogicService sendEmailLogicService=SpringBeans.getEmailLogicService("emailLogicService");
			List<MsgMail> msgMailList=sendEmailLogicService.getAllMsgMail();
			if(CollectionUtils.isNotEmpty(msgMailList)){
				for(MsgMail msgMail:msgMailList){
					String content=msgMail.getContent();
					String rgex = "<img src=\"(.*?)\"";
					List<String> srcList=getSubUtil(content,rgex);
					if(CollectionUtils.isEmpty(srcList)){break;}
					for(String src:srcList){
						String srcStr=src.substring(CebaPathUtil.getProjectContextPath().length(),src.length());
						content=content.replaceAll(src, LogicPathUtil.getBrowserPath(null, srcStr));
					}
					sendEmailLogicService.updateContent(msgMail.getId(),content);
				}
			}

			if(bool){
				CebaConfig.set("FILE_DEFAULT_STORAGE_PATH_FLAG", FileDefaultStoragePathFlagEnum.CHANGE.getFlag());
				CebaConfig.FILE_DEFAULT_STORAGE_PATH_FLAG = FileDefaultStoragePathFlagEnum.CHANGE;
			}

		}
	}

	/**
	 * 正则表达式匹配两个指定字符串中间的内容
	 * @param soap
	 * @return
	 */
	public static List<String> getSubUtil(String soap,String rgex){
		List<String> list = new ArrayList<String>();
		Pattern pattern = Pattern.compile(rgex);// 匹配的模式
		Matcher m = pattern.matcher(soap);
		while (m.find()) {
			int i = 1;
			list.add(m.group(i));
			i++;
		}
		return list;
	}

	/**
	 * 返回单个字符串，若匹配到多个的话就返回第一个，方法与getSubUtil一样
	 * @param soap
	 * @param rgex
	 * @return
	 */
	public static String getSubUtilSimple(String soap,String rgex){
		Pattern pattern = Pattern.compile(rgex);// 匹配的模式
		Matcher m = pattern.matcher(soap);
		while(m.find()){
			return m.group(1);
		}
		return "";
	}

}
